/*
 * Copyright 2023-2085 xujin <ceo@itgrail.com>
 *
 * Licensed under the Grail License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://itgrail.com/docs?id=3&catalogId=87
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.itgrail.pilot.app.command;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.itgrail.grail.shiro.util.JwtUtil;
import com.itgrail.pilot.app.command.cmo.LoginUserCmd;
import com.itgrail.pilot.app.command.co.LogInCO;
import com.itgrail.pilot.domain.user.contant.OkrConstants;
import com.itgrail.pilot.domain.user.event.CreateUserEvent;
import com.itgrail.pilot.infrastructure.tunnel.db.dao.*;
import com.itgrail.pilot.infrastructure.tunnel.db.dataobject.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import com.itgrail.grail.cqrs.annotation.CmdHandler;
import com.itgrail.grail.cqrs.command.CommandExecutorI;
import com.itgrail.grail.dto.ResultData;
import com.itgrail.grail.ddd.event.EventBus;

import java.util.List;

@Slf4j
@CmdHandler
public class LoginUserCmdExe implements CommandExecutorI<ResultData, LoginUserCmd> {
    @Autowired
    private EventBus eventBus;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DepartmentMapper deptMapper;

    @Autowired
    private DepartmentUserMapper departmentUserMapper;

    @Autowired
    private UserRolesMapper userRolesMapper;

    @Override
    public ResultData execute(LoginUserCmd loginUserCmd) {
        ResultData resultData = new ResultData<>();
        if (null == loginUserCmd) {
            log.error("登录失败:{}", JSON.toJSONString(loginUserCmd));
            resultData.setMsgCode("402");
            resultData.setMsgContent("登录失败，用户名或密码错误！");
            return resultData;
        }
        String userName = loginUserCmd.getUserName();
        String passoWord = loginUserCmd.getPassWord();
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(userName, passoWord);
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            LogInCO logInCO = new LogInCO().setUserName(userName).setToken(JwtUtil.createToken(userName));
            getUserInfo(logInCO);
            //校验通过
            resultData.setData(logInCO);
            try {
                createUserByEvent(logInCO);
            } catch (Exception e) {
                log.error("create user by event fail:", e);
            }
        } catch (Exception ex) {
            log.error("登录失败:", ex);
            resultData.setMsgCode("402");
            resultData.setMsgContent("登录失败，用户名或密码错误！");
            return resultData;
        }

        return resultData;
    }

    private void getUserInfo(LogInCO logInCO) {
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", OkrConstants.NOT_DELETED);
        queryWrapper.eq("account", logInCO.getUserName());
        UserDO userDO = userMapper.selectOne(queryWrapper);
        if (null != userDO && StringUtils.isNotEmpty(userDO.getMobile())) {
            Integer userId = userDO.getUserId();
            if (userId != null) {
                logInCO.setUserId(userId.toString());
            }
            logInCO.setPersonName(userDO.getName());
            logInCO.setPersonCode(userDO.getPersonCode());
            logInCO.setMobile(userDO.getMobile());
            logInCO.setDingUrl(userDO.getDingUrl());

            List<DepartmentUserDO> departmentUserDOList= departmentUserMapper.queryByUserId(userId);
            if(null!=departmentUserDOList&&departmentUserDOList.size()>0){
                LambdaQueryWrapper<DepartmentDO> deptDOQueryWrapper = new LambdaQueryWrapper<>();
                deptDOQueryWrapper.eq(DepartmentDO::getId, departmentUserDOList.get(0).getDepartmentId());
                DepartmentDO deptDO = deptMapper.selectOne(deptDOQueryWrapper);
                if (null != deptDO) {
                    logInCO.setDeptId(deptDO.getId());
                    logInCO.setDeptName(deptDO.getName());
                }
            }
        }
        String account = logInCO.getUserName();
        QueryWrapper<UserRolesDO> userRolesDOQueryWrapper = new QueryWrapper<>();
        userRolesDOQueryWrapper.eq("username", account);
        userRolesDOQueryWrapper.eq("role", "ADMIN");
        UserRolesDO userRolesDO = userRolesMapper.selectOne(userRolesDOQueryWrapper);
        if (null != userRolesDO) {
            logInCO.setAdmin(true);
        } else {
            logInCO.setAdmin(false);
        }

    }

    private void createUserByEvent(LogInCO logInCO) {
        CreateUserEvent createUserEvent = new CreateUserEvent();
        String userId = logInCO.getUserId();
        if (StringUtils.isNotEmpty(userId)) {
            createUserEvent.setCurrentUserId(Integer.valueOf(userId));
        }
        createUserEvent.setMobile(logInCO.getMobile());
        createUserEvent.setAccount(logInCO.getUserName());
        createUserEvent.setRole("USER");
        log.info("创建用户信息:{}", JSON.toJSONString(createUserEvent));
        eventBus.asyncPublishEvent(createUserEvent);
    }
}
